import argparse
import traceback

async def main(ob, args):
    parser = argparse.ArgumentParser(prog='build', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    subparsers = parser.add_subparsers(dest='part')

    parser_here = subparsers.add_parser('here', aliases=['h'])

    parser_short = subparsers.add_parser('short', aliases=['s'])
    parser_short.add_argument('txt', nargs='+', type=str, help='short description of here')

    parser_long = subparsers.add_parser('long', aliases=['l'], formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser_long.add_argument('-a', '--append', action='store_true', default=False, help='append text')
    parser_long.add_argument('-A', '--ascii', action='store_true', default=False, help='Ascii art')
    parser_long.add_argument('--prefix', metavar='<str>', type=str, default=None, help='prefix for text, for STYLE of ascii art')
    #the following for ascii art
    parser_long.add_argument('txt', nargs='+', type=str, help='long description of here')
    parser_long.add_argument('-H', '--dst_height', metavar='<h>', type=int, default=24, help='output height(lines)')
    parser_long.add_argument('-W', '--width_fix', metavar='<n>', type=float, default=0, help='0 or None: do nothing; > 0: relate to width; < 0: relate to height')
    parser_long.add_argument('-F', '--font_path', metavar='<path>', type=str, default='0', help='0/1/2 or path of *.ttf. To find it from fonts folder of os system')
    parser_long.add_argument('--block', metavar='<c>', type=str, default='.', help='Character for black block')
    parser_long.add_argument('--blank', metavar='<c>', type=str, default=' ', help='Character for white block')
    parser_long.add_argument('-K', '--kerning', metavar='<k>', type=float, default=0, help='fix space between two characters, (> -1)')
    parser_long.add_argument('-P', '--padding', metavar='<p>', type=int, default=0, help='add blank space every line')
    parser_long.add_argument('-f', '--fast', action='store_true', default=False, help='use faster shape match algorithm')
    parser_long.add_argument('--char_set', metavar='<str>', type=str, default=None, help='Character settings, default 0x33-0x7e')

    parser_short = subparsers.add_parser('chown', aliases=['ch'])
    parser_short.add_argument('to', type=str, help='Change owner of here')

    if not args:
        await ob.m.tell_user(ob, f'{parser.format_help()}')
        return True

    args, exit_code, msg = ob.m.Cmds.safe_parse_args(parser, args.split())
    if not args:
        if msg: await ob.m.tell_user(ob, f'{msg}')
        return exit_code == 0

    location = ob.data.get('location', None)
    if not location or location not in ob.m.space_ob:
        await ob.m.tell_user(ob, 'Your location cannot be detected.\n')
        return False

    data = ob.m.spaces.get(location, None)
    owner = data.get('owner', None) if data else None
    here = ob.m.get_space(location)

    part = vars(args).pop('part')

    if part in ('here', 'h'):
        if data:
            if owner:
                msg = f'This land already has an owner, and it is [{owner}].\n'
            else:
                data['owner'] = ob.uid
                msg = 'Congratulations on becoming the new owner of this land.\n'
        else:
            here.init_data(ob.uid)
            msg = 'After a period of hard work, you have become the owner of this land.\n'
    elif part in ('short', 's'):
        if not await _check_owner(owner, ob): return False

        sign = ' '.join(args.txt)
        sign = ob.m.Style.escape(sign)

        if len(sign) > 128:
            await ob.m.tell_user(ob, 'The text of a place name sign cannot exceed 128 characters.\n')
            return False

        data['short'] = sign
        msg = 'You have constructed a place name sign.\n'
    elif part in ('long', 'l'):
        if not await _check_owner(owner, ob): return False

        is_append = vars(args).pop('append')
        is_ascii = vars(args).pop('ascii')
        args.txt = ' '.join(args.txt)

        if is_ascii:
            if len(args.txt) > 7:
                await ob.m.tell_user(ob, 'ascii art support lenght <= 7.\n')
                return False

            prefix = vars(args).pop('prefix')

            try:
                at = ob.m.ascii_art.AsciiTxt(**vars(args))
                delay = '2-4' if args.fast else '15-20'
                await ob.m.tell_user(ob, f'Ascii Txt building... It will take about {delay} seconds\n')
                img_txt = at()
                await ob.m.tell_user(ob, f'Ascii Txt size: {at.dst_w}x{at.dst_h}\n')
                line_width = at.dst_w + at.padding 
                if line_width > 120:
                    await ob.m.tell_user(ob, f'image text too big to display: {line_width}\n')
                    return False
            except:
                await ob.m.tell_user(ob, f'{traceback.format_exc()}')
                return False

            if prefix:
                desc = ob.m.Style.escape(prefix, False) + img_txt + ob.m.Style.N
            else:
                desc = img_txt
        else:
            desc = ob.m.Style.escape(args.txt)
            if len(desc) > 1024:
                await ob.m.tell_user(ob, 'You can carry a maximum of 1024 bricks at a time.\n')
                return False

        if is_append:
            if 'long' not in data: data['long'] = ''
            data['long'] += desc + '\n'
        else:
            data['long'] = desc + '\n'

        msg = f'You diligently carried {len(desc)} bricks to construct a building on this piece of land.\n'
    elif part in ('chown', 'ch'):
        if not await _check_owner(owner, ob): return False

        new_owner = args.to

        if new_owner not in ob.m.users:
            await ob.m.tell_user(ob, f"We don't have anyone by the name of {new_owner}.\n")
            return False

        if owner == new_owner:
            await ob.m.tell_user(ob, f"You need not do this.\n")
            return False

        data['owner'] = new_owner
        await ob.m.tell_users(f"The ownership of the plot located at position {location} was transferred from {owner} to {new_owner}.\n")
        msg = 'Congratulations!\n'
    else:
        msg = 'OH!'

    await ob.m.tell_user(ob, msg)
    return True


async def _check_owner(owner, ob):
    if not owner or owner != ob.uid:
        msg = 'You are not yet the owner of this land.\n'
        if not owner:
            msg += 'You can try: build here\n'
        else:
            msg += f'You could make a proposal to {owner} for acquiring the land: build chown {ob.uid}\n'
        await ob.m.tell_user(ob, msg) 
        return False
    return True

